﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace MalaCSharp
{
    ///-------------------------------------------------------------------------------------------------
    /// <summary> A Mala game. </summary>
    ///-------------------------------------------------------------------------------------------------
    public class MalaGame
    {
        #region Properties

        public String Name { get; set; }
        public String RomOf { get; set; }
        public String CloneOf { get; set; }
        public String Sourcefile { get; set; }

        public String Description { get; set; }
        public Int32 Year { get; set; }
        public String Manufacturer { get; set; }
        public String Genre { get; set; }

        public Int32 InputButtons { get; set; }
        public Int32 InputCoins { get; set; }
        public String InputPlayers { get; set; }
        public String InputControl { get; set; }

        public String VideoScreen { get; set; }
        public String VideoOrientation { get; set; }
        public Int32 VideoWidth { get; set; }
        public Int32 VideoHeight { get; set; }

        public String DriverStatus { get; set; }
        public String DriverColor { get; set; }
        public String DriverSound { get; set; }
        public String DriverEmulation { get; set; }
        public String DriverGraphic { get; set; }

        public String Controls { get; set; }
        public String JoyUp { get; set; }
        public String JoyDown { get; set; }
        public String JoyLeft { get; set; }
        public String JoyRight { get; set; }
        public String Button1 { get; set; }
        public String Button2 { get; set; }
        public String Button3 { get; set; }
        public String Button4 { get; set; }
        public String Button5 { get; set; }
        public String Button6 { get; set; }
        public String Button7 { get; set; }
        public String Button8 { get; set; }
        public String Details { get; set; }

        public String RomPath { get; set; }
        public String Extension { get; set; }

        public Int32 Played { get; set; }

        #endregion

        #region Constructor(s)

        ///-------------------------------------------------------------------------------------------------
        /// <summary> Default constructor. </summary>
        ///-------------------------------------------------------------------------------------------------
        public MalaGame()
        { }

        ///-------------------------------------------------------------------------------------------------
        /// <summary> Constructor. </summary>
        /// <param name="stream"> The stream to load. </param>
        ///-------------------------------------------------------------------------------------------------
        public MalaGame(Stream stream)
        {
            Load(stream);
        }

        ///-------------------------------------------------------------------------------------------------
        /// <summary> Copy constructor. </summary>
        /// <param name="game"> The mala game to compare to this object. </param>
        ///-------------------------------------------------------------------------------------------------
        public MalaGame(MalaGame game)
        {
            Copy(game);
        }

        #endregion

        #region Public

        ///-------------------------------------------------------------------------------------------------
        /// <summary> Saves to the supplied stream. </summary>
        /// <param name="stream"> The stream to save to. </param>
        ///-------------------------------------------------------------------------------------------------
        public void Save(Stream stream)
        {
            StorageHelper.WriteListBegin(stream);

            StorageHelper.WriteString(stream, Name);
            StorageHelper.WriteString(stream, RomOf);
            StorageHelper.WriteString(stream, CloneOf);
            StorageHelper.WriteString(stream, Sourcefile);

            StorageHelper.WriteString(stream, Description);
            StorageHelper.WriteInt(stream, Year);
            StorageHelper.WriteString(stream, Manufacturer);
            StorageHelper.WriteString(stream, Genre);

            StorageHelper.WriteInt(stream, InputButtons);
            StorageHelper.WriteInt(stream, InputCoins);
            StorageHelper.WriteString(stream, InputPlayers);
            StorageHelper.WriteString(stream, InputControl);

            StorageHelper.WriteString(stream, VideoScreen);
            StorageHelper.WriteString(stream, VideoOrientation);
            StorageHelper.WriteInt(stream, VideoWidth);
            StorageHelper.WriteInt(stream, VideoHeight);

            StorageHelper.WriteString(stream, DriverStatus);
            StorageHelper.WriteString(stream, DriverColor);
            StorageHelper.WriteString(stream, DriverSound);
            StorageHelper.WriteString(stream, DriverEmulation);
            StorageHelper.WriteString(stream, DriverGraphic);

            StorageHelper.WriteString(stream, Controls);
            StorageHelper.WriteString(stream, JoyUp);
            StorageHelper.WriteString(stream, JoyDown);
            StorageHelper.WriteString(stream, JoyLeft);
            StorageHelper.WriteString(stream, JoyRight);
            StorageHelper.WriteString(stream, Button1);
            StorageHelper.WriteString(stream, Button2);
            StorageHelper.WriteString(stream, Button3);
            StorageHelper.WriteString(stream, Button4);
            StorageHelper.WriteString(stream, Button5);
            StorageHelper.WriteString(stream, Button6);
            StorageHelper.WriteString(stream, Button7);
            StorageHelper.WriteString(stream, Button8);
            StorageHelper.WriteString(stream, Details);

            StorageHelper.WriteString(stream, RomPath);
            StorageHelper.WriteString(stream, Extension);

            StorageHelper.WriteInt(stream, Played);

            StorageHelper.WriteListEnd(stream);
        }

        ///-------------------------------------------------------------------------------------------------
        /// <summary> Loads from the given stream. </summary>
        /// <param name="stream"> The stream to load from. </param>
        ///-------------------------------------------------------------------------------------------------
        public void Load(Stream stream)
        {
            StorageHelper.ReadListBegin(stream);

            Name = StorageHelper.ReadString(stream);
            RomOf = StorageHelper.ReadString(stream);
            CloneOf = StorageHelper.ReadString(stream);
            Sourcefile = StorageHelper.ReadString(stream);

            Description = StorageHelper.ReadString(stream);
            Year = StorageHelper.ReadInt(stream);
            Manufacturer = StorageHelper.ReadString(stream);
            Genre = StorageHelper.ReadString(stream);

            InputButtons = StorageHelper.ReadInt(stream);
            InputCoins = StorageHelper.ReadInt(stream);
            InputPlayers = StorageHelper.ReadString(stream);
            InputControl = StorageHelper.ReadString(stream);

            VideoScreen = StorageHelper.ReadString(stream);
            VideoOrientation = StorageHelper.ReadString(stream);
            VideoWidth = StorageHelper.ReadInt(stream);
            VideoHeight = StorageHelper.ReadInt(stream);

            DriverStatus = StorageHelper.ReadString(stream);
            DriverColor = StorageHelper.ReadString(stream);
            DriverSound = StorageHelper.ReadString(stream);
            DriverEmulation = StorageHelper.ReadString(stream);
            DriverGraphic = StorageHelper.ReadString(stream);

            Controls = StorageHelper.ReadString(stream);
            JoyUp = StorageHelper.ReadString(stream);
            JoyDown = StorageHelper.ReadString(stream);
            JoyLeft = StorageHelper.ReadString(stream);
            JoyRight = StorageHelper.ReadString(stream);
            Button1 = StorageHelper.ReadString(stream);
            Button2 = StorageHelper.ReadString(stream);
            Button3 = StorageHelper.ReadString(stream);
            Button4 = StorageHelper.ReadString(stream);
            Button5 = StorageHelper.ReadString(stream);
            Button6 = StorageHelper.ReadString(stream);
            Button7 = StorageHelper.ReadString(stream);
            Button8 = StorageHelper.ReadString(stream);
            Details = StorageHelper.ReadString(stream);

            RomPath = StorageHelper.ReadString(stream);
            Extension = StorageHelper.ReadString(stream);

            Played = StorageHelper.ReadInt(stream);

            StorageHelper.ReadListEnd(stream);
        }

        public void Copy(MalaGame game)
        {
            if (game == null)
                throw new ArgumentNullException("game");

            Name = game.Name;
            RomOf = game.RomOf;
            CloneOf = game.CloneOf;
            Sourcefile = game.Sourcefile;

            Description = game.Description;
            Year = game.Year;
            Manufacturer = game.Manufacturer;
            Genre = game.Genre;

            InputButtons = game.InputButtons;
            InputCoins = game.InputCoins;
            InputPlayers = game.InputPlayers;
            InputControl = game.InputControl;

            VideoScreen = game.VideoScreen;
            VideoOrientation = game.VideoOrientation;
            VideoWidth = game.VideoWidth;
            VideoHeight = game.VideoHeight;

            DriverStatus = game.DriverStatus;
            DriverColor = game.DriverColor;
            DriverSound = game.DriverSound;
            DriverEmulation = game.DriverEmulation;
            DriverGraphic = game.DriverGraphic;

            Controls = game.Controls;
            JoyUp = game.JoyUp;
            JoyDown = game.JoyDown;
            JoyLeft = game.JoyLeft;
            JoyRight = game.JoyRight;
            Button1 = game.Button1;
            Button2 = game.Button2;
            Button3 =game.Button3;
            Button4 = game.Button4;
            Button5 = game.Button5;
            Button6 = game.Button6;
            Button7 = game.Button7;
            Button8 =game.Button8;
            Details = game.Details;

            RomPath = game.RomOf;
            Extension = game.Extension;

            Played = game.Played;
        }

        ///-------------------------------------------------------------------------------------------------
        /// <summary> Returns a <see cref="T:System.String" /> that represents the current
        /// <see cref="T:System.Object" />. </summary>
        /// <returns> A <see cref="T:System.String" /> that represents the current
        /// <see cref="T:System.Object" />. </returns>
        ///-------------------------------------------------------------------------------------------------
        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();

            sb.AppendLine(Name);
            sb.AppendLine("-------");
            sb.AppendLine("RomOf: " + RomOf);
            sb.AppendLine("CloneOf: " + CloneOf);
            sb.AppendLine("SourceFile: " + Sourcefile);

            sb.AppendLine("Description: " + Description);
            sb.AppendLine("Year: " + Year);
            sb.AppendLine("Manufacturer: " + Manufacturer);
            sb.AppendLine("Genre: " + Genre);

            sb.AppendLine("Input Buttons: " + InputButtons);
            sb.AppendLine("Input Coins: " + InputCoins);
            sb.AppendLine("Input Players: " + InputPlayers);
            sb.AppendLine("Input Control: " + InputControl);

            sb.AppendLine("Video Screen: " + VideoScreen);
            sb.AppendLine("Video Orientation: " + VideoOrientation);
            sb.AppendLine("Video Width: " + VideoWidth);
            sb.AppendLine("Video Height: " + VideoHeight);

            sb.AppendLine("Driver Status: " + DriverStatus);
            sb.AppendLine("Driver Color: " + DriverColor);
            sb.AppendLine("Driver Sound: " + DriverSound);
            sb.AppendLine("Driver Emulation: " + DriverEmulation);
            sb.AppendLine("Driver Graphic: " + DriverGraphic);

            sb.AppendLine("Controls: " + Controls);
            sb.AppendLine("Up: " + JoyUp);
            sb.AppendLine("Down: " + JoyDown);
            sb.AppendLine("Left: " + JoyLeft);
            sb.AppendLine("Right: " + JoyRight);
            sb.AppendLine("Button1: " + Button1);
            sb.AppendLine("Button2: " + Button2);
            sb.AppendLine("Button3: " + Button3);
            sb.AppendLine("Button4: " + Button4);
            sb.AppendLine("Button5: " + Button5);
            sb.AppendLine("Button6: " + Button6);
            sb.AppendLine("Button7: " + Button7);
            sb.AppendLine("Button8: " + Button8);
            sb.AppendLine("Details: " + Details);

            sb.AppendLine("RomPath: " + RomPath);
            sb.AppendLine("Extension: " + Extension);

            sb.AppendLine("Played: " + Played);

            return sb.ToString();
        }

        ///-------------------------------------------------------------------------------------------------
        /// <summary> Serves as a hash function for a particular type. </summary>
        /// <returns> A hash code for the current <see cref="T:System.Object" />. </returns>
        ///-------------------------------------------------------------------------------------------------
        public override int GetHashCode()
        {
            if (Name == null)
                return base.GetHashCode();
            else
                return Name.GetHashCode();
        }

        ///-------------------------------------------------------------------------------------------------
        /// <summary> Determines whether the specified <see cref="T:System.Object" /> is equal to the
        /// current <see cref="T:System.Object" />. </summary>
        /// <exception cref="ArgumentNullException"> Thrown when one or more required arguments are null. </exception>
        /// <param name="obj"> The <see cref="T:System.Object" /> to compare with the current
        /// <see cref="T:System.Object" />. </param>
        /// <returns> true if the specified <see cref="T:System.Object" /> is equal to the current
        /// <see cref="T:System.Object" />; otherwise, false. </returns>
        ///-------------------------------------------------------------------------------------------------
        public override bool Equals(object obj)
        {
            if (obj == null)
                throw new ArgumentNullException("obj");
            else
            {
                MalaGame game = obj as MalaGame;
                if (game == null)
                    return false;
                else
                    return Equals(game);
            }
        }

        ///-------------------------------------------------------------------------------------------------
        /// <summary> Determines whether the specified <see cref="T:System.Object" /> is equal to the
        /// current <see cref="T:System.Object" />. </summary>
        /// <param name="game"> The mala game to compare to this object. </param>
        /// <returns> true if the specified <see cref="T:System.Object" /> is equal to the current
        /// <see cref="T:System.Object" />; otherwise, false. </returns>
        ///-------------------------------------------------------------------------------------------------
        public bool Equals(MalaGame game)
        {
            if (!Name.Equals(game.Name, StringComparison.Ordinal))
                return false;

            if (!RomOf.Equals(game.RomOf, StringComparison.Ordinal))
                return false;

            if (!CloneOf.Equals(game.CloneOf, StringComparison.Ordinal))
                return false;

            if (!Sourcefile.Equals(game.Sourcefile, StringComparison.Ordinal))
                return false;

            if (!Description.Equals(game.Description, StringComparison.Ordinal))
                return false;

            if (Year != game.Year)
                return false;

            if (!Manufacturer.Equals(game.Manufacturer, StringComparison.Ordinal))
                return false;

            if (!Genre.Equals(game.Genre, StringComparison.Ordinal))
                return false;

            if (InputButtons != game.InputButtons)
                return false;

            if (InputCoins != game.InputCoins)
                return false;

            if (!InputPlayers.Equals(game.InputPlayers, StringComparison.Ordinal))
                return false;

            if (!InputControl.Equals(game.InputControl, StringComparison.Ordinal))
                return false;

            if (!VideoScreen.Equals(game.VideoScreen, StringComparison.Ordinal))
                return false;

            if (!VideoOrientation.Equals(game.VideoOrientation, StringComparison.Ordinal))
                return false;

            if (VideoWidth != game.VideoWidth)
                return false;

            if (VideoHeight != game.VideoHeight)
                return false;

            if (!DriverStatus.Equals(game.DriverStatus, StringComparison.Ordinal))
                return false;

            if (!DriverColor.Equals(game.DriverColor, StringComparison.Ordinal))
                return false;

            if (!DriverSound.Equals(game.DriverSound, StringComparison.Ordinal))
                return false;

            if (!DriverEmulation.Equals(game.DriverEmulation, StringComparison.Ordinal))
                return false;

            if (!DriverGraphic.Equals(game.DriverGraphic, StringComparison.Ordinal))
                return false;

            if (!Controls.Equals(game.Controls, StringComparison.Ordinal))
                return false;

            if (!JoyUp.Equals(game.JoyUp, StringComparison.Ordinal))
                return false;

            if (!JoyDown.Equals(game.JoyDown, StringComparison.Ordinal))
                return false;

            if (!JoyLeft.Equals(game.JoyLeft, StringComparison.Ordinal))
                return false;

            if (!JoyRight.Equals(game.JoyRight, StringComparison.Ordinal))
                return false;

            if (!Button1.Equals(game.Button1, StringComparison.Ordinal))
                return false;

            if (!Button2.Equals(game.Button2, StringComparison.Ordinal))
                return false;

            if (!Button3.Equals(game.Button3, StringComparison.Ordinal))
                return false;

            if (!Button4.Equals(game.Button4, StringComparison.Ordinal))
                return false;

            if (!Button5.Equals(game.Button5, StringComparison.Ordinal))
                return false;

            if (!Button6.Equals(game.Button6, StringComparison.Ordinal))
                return false;

            if (!Button7.Equals(game.Button7, StringComparison.Ordinal))
                return false;

            if (!Button8.Equals(game.Button8, StringComparison.Ordinal))
                return false;

            if (!RomPath.Equals(game.RomPath, StringComparison.Ordinal))
                return false;

            if (!Extension.Equals(game.Extension, StringComparison.Ordinal))
                return false;

            if (Played != game.Played)
                return false;

            return true;
        }

        #endregion
    }
}
